/**
 * 
 */
package jvs.core.http.handler;


import java.io.FileFilter;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLDecoder;
import java.security.Principal;
import java.util.Date;

import jvs.core.http.Message;
import jvs.core.http.Request;
import jvs.core.http.Response;
import jvs.tea.html.FolderTemplateInputStream;
import jvs.vfs.FileSystem;
import x.java.io.File;

/**
 * @author qiangli
 * 
 */
public class FileHandler extends Handler {

	protected String root;

	public FileHandler() {
		this.root = "v:/";
	}

	public FileHandler(String root) {
		this.root = root;
	}

	protected File createFile(String path) throws IOException {
		path = URLDecoder.decode(path, "UTF-8");
		return new x.java.io.File(root, path);
	}

	protected InputStream createFileInputStream(File file) throws IOException {

		return ((x.java.io.File) file).getInputStream();
		// new x.java.io.FileInputStream(file);
	}

	@Override
	protected void doGet(Request req, Response res) throws Exception {
		File file = createFile(req.path);

		log("process file: " + file.getPath());

		try {
			if (!file.exists()) {
				fileNotFound(req, res, file);
				return;
			}
			if (!file.canRead()) {
				fileAccessDenied(req, res, file);
				return;
			}
			
			if (file.isDirectory()) {
				listFiles(req, res, file);
				return;
			}
			
			//check permission
			if (!checkAuth(req, res, file)) {
				fileAccessDenied(req, res, file);
				return;
			}
			
			readFile(req, res, file);
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	protected void fileAccessDenied(Request req, Response res, File file) {
		String c = "<html><body><h1>Access denied: " + file.getPath()
				+ "</h1></body></html>";
		res.statusCode = Response.CODE401;
		res.contentType = Response.TYPE_TEXT_HTML;
		res.send(c);
	}

	protected void fileNotFound(Request req, Response res, File file) {
		String c = "<html><body><h1>File " + file.getPath()
				+ " not found</h1></body></html>";
		res.statusCode = Response.CODE404;
		res.contentType = Response.TYPE_TEXT_HTML;
		res.send(c);
	}

	protected String guessType(File file) {
		return FileSystem.getFileSystem().guessType(file);
	}

	protected void listFiles(final Request req, final Response res, final File file)
			throws Exception {
		res.statusCode = Response.CODE200;
		res.contentType = Response.TYPE_TEXT_HTML;
		res.lastModified = file.lastModified();
		res.date = System.currentTimeMillis();
		res.transferEncoding = Response.TRANSFER_ENCODING_CHUNKED;
		FileFilter ff = new FileFilter() {	
			public boolean accept(java.io.File f) {
				return checkAuth(req, res, f);
			}	
		};
		int fidx = 0;
		try {
			fidx = Integer.parseInt(req.getParam("fileindex"));
		} catch (Exception e) {
			
		}
		InputStream is = new FolderTemplateInputStream(req.context.baseUri, file, ff, fidx);
		res.send(is, true);
	}

	protected void readFile(Request req, Response res, File file)
			throws Exception {
		try {
			if (req.ifModifiedSince != null) {
				Date ims = Message.parseRFC1123(req.ifModifiedSince);
				if (ims.getTime() >= file.lastModified()) {
					res.notModified(System.currentTimeMillis());
					log("Not modified since: "+ims);
					return;
				}
			}
		} catch (Exception e) {
			//
		}
		String type = guessType(file);
		//
		res.statusCode = Response.CODE200;
		res.contentType = type;
		res.lastModified = file.lastModified();
		res.date = System.currentTimeMillis();
		res.transferEncoding = Response.TRANSFER_ENCODING_CHUNKED;
		InputStream is = createFileInputStream(file);
		res.send(is, true);
	}

	protected boolean checkAccess(File file, Principal user) {
		return false;
	}

	protected boolean checkAuth(Request req, Response res, java.io.File file) {
		String p = file.getPath();
		if (file.isDirectory()) {
			p = p.endsWith("/")? p : p+"/";
		}
		//TODO for testing
		return true; //return FileHelper.checkAuth(req.context, p);
	}
}
